home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1997 October / pcx14_9710.iso / swag / delphi.swg / 0227_tRichButton Component.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-03-04  |  21.2 KB  |  544 lines

  1. {*******************************************************************************
  2.   TRichButton
  3.   Copyright ⌐ 1997 Mentor Computer Solutions
  4.   Version 1.0 revised February 2, 1997
  5.  
  6.   Author:       Garret Wilson
  7.                 Garret@MentorComputer.com
  8.  
  9.   Company:      Mentor Computer Solutions
  10.                 RR 2 Box 246
  11.                 Chelsea, OK 74016 USA
  12.                 (918) 789-2734
  13.                 http://www.MentorComputer.com
  14.  
  15.   Status:       Freeware. Source may be redistributed in whole, providing that
  16.                 the copyright information is also included.
  17.  
  18.   Description:  TRichButton provides a button that can include rich text,
  19.                 including bold, italics, different fonts, etc. To use
  20.                 TRichButton, access the Lines, Font, Color, DefAttributes,
  21.                 SelAttributes, and Paragraph properties, which function
  22.                 identically to those that come with the standard TRichEdit
  23.                 control.
  24.  
  25.   Acknowledgements: TRichButton was developed in part by referring to the
  26.                     Borland source code for TCustomPanel and TRichEdit. Some
  27.                     features of TRichButton originated from ideas implemented in
  28.                     TTransBitmap, which is Copyright ⌐ 1996 Alan GARNY,
  29.                     gry@physiol.ox.ac.uk, http://www.physiol.ox.ac.uk/~gry
  30.                     and these instances are indicated.
  31. *******************************************************************************}
  32.  
  33. unit RichButton;
  34.  
  35. interface
  36.  
  37. uses
  38.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ComCtrls, ExtCtrls;
  39.  
  40. type
  41.  
  42.   TRichButtonState = (stUp, stDown, stDisabled);
  43.  
  44.   TRichButton = class(TCustomControl)
  45.   private
  46.     FAlignment: TAlignment;     {storage for properties}
  47.     FAllowDown: Boolean;
  48.     FBevelInner: TPanelBevel;
  49.     FBevelOuter: TPanelBevel;
  50.     FBevelWidth: TBevelWidth;
  51.     FBorderWidth: TBorderWidth;
  52.     FBorderStyle: TBorderStyle;
  53.     FFocus: Boolean;
  54.     FFocusColor: TColor;
  55.     FFocusWidth: TWidth;
  56.     FFullRepaint: Boolean;
  57.     FLocked: Boolean;
  58.     FState: TRichButtonState;
  59.     FOnResize: TNotifyEvent;
  60.     FSelAttributes: TTextAttributes;
  61.     FDefAttributes: TTextAttributes;
  62.     FParagraph: TParaAttributes;
  63.     HasFocus:Boolean;     {variables used internally}
  64.     MouseCaught:Boolean;
  65.     OrigState:TRichButtonState;
  66.     RichEdit:TRichEdit;
  67.     procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  68.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  69.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  70.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  71.     procedure CMIsToolControl(var Message: TMessage); message CM_ISTOOLCONTROL;
  72.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  73.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  74.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  75.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  76.     procedure SetAlignment(Value: TAlignment);
  77.     procedure SetAllowDown(Value:Boolean);  {modified from TTransBitmap}
  78.     procedure SetBevelInner(Value: TPanelBevel);
  79.     procedure SetBevelOuter(Value: TPanelBevel);
  80.     procedure SetBevelWidth(Value: TBevelWidth);
  81.     procedure SetBorderWidth(Value: TBorderWidth);
  82.     procedure SetBorderStyle(Value: TBorderStyle);
  83.     procedure SetFocus(Value:Boolean);  {modified from TTransBitmap}
  84.     procedure SetFocusColor(Value:TColor);  {modified from TTransBitmap}
  85.     procedure SetFocusWidth(Value:TWidth);  {modified from TTransBitmap}
  86.     function GetLines:TStrings;
  87.     procedure SetLines(Value:TStrings);
  88.     procedure SetState(Value:TRichButtonState); {modified from TTransBitmap}
  89.     procedure ReadData(Reader: TReader);
  90.         {internal routines}
  91.     function GetWorkRect:TRect;  {modified from TTransBitmap}
  92.   protected
  93.     procedure CreateParams(var Params: TCreateParams); override;
  94.     procedure CreateWnd; override;
  95.     procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  96.     procedure Paint; override;
  97.     procedure Resize; dynamic;
  98.     property FullRepaint: Boolean read FFullRepaint write FFullRepaint default True;
  99.   public
  100.     constructor Create(AOwner: TComponent); override;
  101.     property DefAttributes:TTextAttributes read FDefAttributes write FDefAttributes; {properties stored in TRichEdit}
  102.     property SelAttributes:TTextAttributes read FSelAttributes write FSelAttributes;
  103.     property Paragraph:TParaAttributes read FParagraph;
  104.   published
  105.     property Align;
  106.     property Alignment:TAlignment read FAlignment write SetAlignment default taCenter;
  107.     property AllowDown:Boolean read FAllowDown write SetAllowDown default False;
  108.     property BevelInner:TPanelBevel read FBevelInner write SetBevelInner default bvNone;
  109.     property BevelOuter:TPanelBevel read FBevelOuter write SetBevelOuter default bvRaised;
  110.     property BevelWidth:TBevelWidth read FBevelWidth write SetBevelWidth default 2;
  111.     property BorderWidth:TBorderWidth read FBorderWidth write SetBorderWidth default 0;
  112.     property BorderStyle:TBorderStyle read FBorderStyle write SetBorderStyle default bsNone;
  113.     property DragCursor;
  114.     property DragMode;
  115.     property Enabled;
  116.     property Color default clBtnFace;
  117.     property Ctl3D;
  118.     property Focus:Boolean read FFocus write SetFocus default False;
  119.     property FocusColor:TColor read FFocusColor write SetFocusColor default clHighlight;
  120.     property FocusWidth:TWidth read FFocusWidth write SetFocusWidth default 2;
  121.     property Font;
  122.     property Height default 25;
  123.     property Locked:Boolean read FLocked write FLocked default False;
  124.     property ParentColor default False;
  125.     property ParentCtl3D;
  126.     property ParentFont;
  127.     property ParentShowHint;
  128.     property PopupMenu;
  129.     property ShowHint;
  130.     property State:TRichButtonState read FState Write SetState default stUp;
  131.     property TabOrder;
  132.     property TabStop;
  133.     property Visible;
  134.     property Width default 75;
  135.     property OnClick;
  136.     property OnDblClick;
  137.     property OnDragDrop;
  138.     property OnDragOver;
  139.     property OnEndDrag;
  140.     property OnEnter;
  141.     property OnExit;
  142.     property OnMouseDown;
  143.     property OnMouseMove;
  144.     property OnMouseUp;
  145.     property OnResize: TNotifyEvent read FOnResize write FOnResize;
  146.     property OnStartDrag;
  147.     property Lines:TStrings read GetLines write SetLines; {properties stored in TRichEdit}
  148.   end;
  149.  
  150. procedure Register;
  151.  
  152. implementation
  153.  
  154. procedure Register;
  155. begin
  156.   RegisterComponents('Additional', [TRichButton]);
  157. end;
  158.  
  159. constructor TRichButton.Create(AOwner: TComponent);
  160. begin
  161.   inherited Create(AOwner);
  162.   ControlStyle := [csAcceptsControls, csCaptureMouse, csOpaque, csDoubleClicks, csReplicatable];
  163.   RichEdit:=TRichEdit.Create(Self); {create the RTF control}
  164.   RichEdit.Parent:=Self;  {set the TRichButton as the parent}
  165.   FDefAttributes:=RichEdit.DefAttributes;  {use the DefAttributes of the RichEdit}
  166.   FSelAttributes:=RichEdit.SelAttributes;  {use the SelAttributes of the RichEdit}
  167.   FParagraph:=RichEdit.Paragraph;  {use the Paragraph of the RichEdit}
  168.   Width:=75;
  169.   Height:=25;
  170.   FAlignment := taCenter;
  171.   FAllowDown:=False;
  172.   BevelOuter := bvRaised;
  173.   BevelWidth:=2;
  174.   FBorderStyle := bsNone;
  175.   Color:=clBtnFace;
  176.   FFocus:=False;
  177.   FFocusColor:=clHighlight;
  178.   FFocusWidth:=2;
  179.   FFullRepaint := True;
  180.   ParentColor:=False;
  181.   FState:=stUp;
  182.   MouseCaught:=False;
  183.   HasFocus:=False;
  184. end;
  185.  
  186. procedure TRichButton.CreateParams(var Params: TCreateParams);
  187. const
  188.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  189. begin
  190.   inherited CreateParams(Params);
  191.   with Params do
  192.   begin
  193.     Style := Style or BorderStyles[FBorderStyle];
  194.     if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then
  195.     begin
  196.       Style := Style and not WS_BORDER;
  197.       ExStyle := ExStyle or WS_EX_CLIENTEDGE;
  198.     end;
  199.   end;
  200. end;
  201.  
  202. procedure TRichButton.CreateWnd;
  203. begin
  204.   inherited CreateWnd;  {call the inherited CreatWnd() procedure}
  205.   RichEdit.BorderStyle:=bsNone; {don't show a border on the RTF control}
  206.   RichEdit.Enabled:=False;  {disable the RTF control altogether, to get rid of the cursor}
  207.   RichEdit.ReadOnly:=True;  {don't allow the rich text to be changed}
  208.   RichEdit.TabStop:=False;  {don't allow the rich text to tabbed to}
  209.   RichEdit.ParentColor:=False;  {don't use the parent color}
  210.   RichEdit.ParentCtl3D:=False;  {don't use the parent's Ctl3D style}
  211.   RichEdit.ParentFont:=False;  {don't use the parent font}
  212.   RichEdit.Font:=Font;  {set the RichEdit to the same font as the button}
  213.   RichEdit.Color:=Color;  {set the RichEdit to the same color as the button}
  214.   if csDesigning in ComponentState then {if we are designing the component}
  215.   begin
  216.     RichEdit.Paragraph.Alignment:=taCenter; {center the text}
  217.     RichEdit.Lines.Add(Name); {show the name of the control}
  218.   end;
  219. end;
  220.  
  221. procedure TRichButton.CMTextChanged(var Message: TMessage);
  222. begin
  223.   Invalidate;
  224. end;
  225.  
  226. procedure TRichButton.CMColorChanged(var Message: TMessage);
  227. begin
  228.   inherited;
  229.   if Parent<>Nil then {if we have a parent (for some reason, we must have this or an error will occur upon creation)}
  230.     RichEdit.Color:=Color;  {set the RichEdit to the same color}
  231. end;
  232.  
  233. procedure TRichButton.CMFontChanged(var Message: TMessage);
  234. begin
  235.   inherited;
  236.   RichEdit.Font:=Font;  {set the RichEdit to the same font}
  237. end;
  238.  
  239. procedure TRichButton.CMCtl3DChanged(var Message: TMessage);
  240. begin
  241.   if NewStyleControls and (FBorderStyle = bsSingle) then RecreateWnd;
  242.   inherited;
  243. end;
  244.  
  245. procedure TRichButton.CMIsToolControl(var Message: TMessage);
  246. begin
  247.   if not FLocked then Message.Result := 1;
  248. end;
  249.  
  250. procedure TRichButton.Resize;
  251. begin
  252.   RichEdit.BoundsRect:=GetWorkRect;  {change the size of the RTF control}
  253.   if FullRepaint then Invalidate;
  254.   if Assigned(FOnResize) then FOnResize(Self);
  255. end;
  256.  
  257. procedure TRichButton.WMSize(var Message: TWMSize);
  258. begin
  259.   inherited;
  260.   if not (csLoading in ComponentState) then Resize;
  261. end;
  262.  
  263. procedure TRichButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); {modified from TTransBitmap}
  264. var
  265.   rect:TRect;
  266.   overControl:Boolean;
  267. begin
  268.   inherited MouseDown(Button, Shift, X, Y); {call the inherited MouseDown() procedure}
  269.   rect:=GetWorkRect;  {find the working area of the button}
  270.   overControl:=(X>=rect.Left) and (x<=rect.Right) and (y>=rect.Top) and (y<=rect.Bottom); {see if the mouse is inside the pressable part of the button}
  271.   if (overControl) and (Button=mbLeft) and (FState<>stDisabled) then {if this was the left mouse button, and the button isn't disabled}
  272.   begin
  273.     MouseCaught:=True;  {show that the left mouse button has been pressed down on the button}
  274.     OrigState:=FState;  {keep track of the original state of the button, in case we allow it to stay down}
  275.     if FState<>stDown then  {if the button isn't down already, put it down}
  276.     begin
  277.       FState:=stDown; {put the button down}
  278.       Realign;  {realign the controls in the button}
  279.       Invalidate;  {invalidate the button for repainting}
  280.     end;
  281.   end;
  282. end;
  283.  
  284. procedure TRichButton.MouseMove(Shift: TShiftState; X, Y: Integer); {modified from TTransBitmap}
  285. var
  286.   newState:TRichButtonState;
  287.   needRepaint:Boolean;
  288.   newHasFocus:Boolean;
  289.   rect:TRect;
  290. begin
  291.   inherited MouseMove(Shift, X, Y); {call the inherited MouseMove() procedure}
  292.   needRepaint:=False; {assume we don't need to repaint the button}
  293.   rect:=GetWorkRect;  {find the working area of the button}
  294.   newHasFocus:=(X>=rect.Left) and (x<=rect.Right) and (y>=rect.Top) and (y<=rect.Bottom); {see if the mouse is still inside the button}
  295.   if HasFocus<>newHasFocus then {if we have went to a different focus state by the mouse movement}
  296.   begin
  297.     HasFocus:=newHasFocus;  {show our new focus state}
  298.     needRepaint:=FFocus;  {if should accept show focus, we should repaint}
  299.   end;
  300.   if MouseCaught then {if the mouse was originally clicked on the button}
  301.   begin
  302.     if not FAllowDown or (OrigState<>stDown) then {if we don't allow the button to be down (or it isn't down, anyway)}
  303.     begin
  304.       if HasFocus then  {update the state of the button, based on whether the mouse is inside the button or not}
  305.         newState:=stDown  {if the mouse is inside, put the button down}
  306.       else                  {if the mouse is outside}
  307.         newState:=stUp;       {bring the button up}
  308.       if newState<>FState then  {if the state has changed}
  309.       begin
  310.         FState:=newState; {change the state permanently}
  311.         needRepaint:=True;  {show that we should repaint the button}
  312.       end;
  313.     end;
  314.   end
  315.   else  {if the mouse is just moving over the control, and wasn't originally click in the control}
  316.     MouseCapture:=FFocus and HasFocus; {if we should show focus, and we have the focus, send messages to the control so we'll know when we lose focus}
  317.   if needRepaint then {if we need to repaint}
  318.   begin
  319.     Realign;  {realign the controls in the button}
  320.     Invalidate;  {invalidate the button for repainting}
  321.   end;
  322. end;
  323.  
  324. procedure TRichButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); {modified from TTransBitmap}
  325. var
  326.   overControl:Boolean;
  327.   rect:TRect;
  328. begin
  329.   inherited MouseUp(Button, Shift, X, Y); {call the inherited MouseUp() procedure}
  330.   if MouseCaught then {if the mouse was originally clicked over the control}
  331.   begin
  332.     MouseCaught:=False; {show that the mouse is no longer caught}
  333.     rect:=GetWorkRect;  {find the working area of the button}
  334.     overControl:=(X>=rect.Left) and (x<=rect.Right) and (y>=rect.Top) and (y<=rect.Bottom); {see if the mouse is still inside the button}
  335.     if FAllowDown and overControl then  {if we should allow the button to stay down, and the mouse button was released over the control}
  336.     begin
  337.       if OrigState=stDown then FState:=stUp else FState:=stDown;  {set the new state to the opposite of what it was originally}
  338.     end
  339.     else  {if this is a typical "non-stay-down" button}
  340.       FState:=stUp; {the button goes up after the mouse is released}
  341.     HasFocus:=False;  {show that we no longer have the focus}
  342.     Realign;  {realign the controls in the button}
  343.     Invalidate;  {invalidate the button for repainting}
  344.     if overControl then Click;  {if they released the mouse button over the control, call the OnClick() event}
  345.   end;
  346. end;
  347.  
  348. function TRichButton.GetWorkRect:TRect;  {modified from TTransBitmap}
  349. var
  350.   delta:Integer;  {number of units to remove from left, right, top, and bottom to get the work rectangle}
  351. begin
  352.   delta:=FBorderWidth;  {always start with the border width}
  353.   if FFocus then    {if we show the focus when the mouse moves over the button}
  354.     Inc(delta, FFocusWidth);    {allow for the focus rectangle}
  355.   if FBevelOuter<>bvNone then {if we have an outer bevel}
  356.     Inc(delta, FBevelWidth);  {take the outer bevel away from our work rectangle}
  357.   if FBevelInner<>bvNone then {if we have an inner bevel}
  358.     Inc(delta, FBevelWidth);  {take the inner bevel away from our work rectangle}
  359.   Result:=GetClientRect;  {get the coordinates of the control}
  360.   InflateRect(Result, -delta, -delta);  {remove the non-work areas from our work rectangle}
  361. end;
  362.  
  363. procedure TRichButton.AlignControls(AControl: TControl; var Rect: TRect);
  364. var
  365.   BevelSize: Integer;
  366. begin
  367.   BevelSize := BorderWidth;
  368.   if BevelOuter <> bvNone then Inc(BevelSize, BevelWidth);
  369.   if BevelInner <> bvNone then Inc(BevelSize, BevelWidth);
  370.   InflateRect(Rect, -BevelSize, -BevelSize);
  371.   inherited AlignControls(AControl, Rect);
  372. end;
  373.  
  374. procedure TRichButton.ReadData(Reader: TReader);
  375. begin
  376.   ShowHint := Reader.ReadBoolean;
  377. end;
  378.  
  379. procedure TRichButton.Paint;
  380. var
  381.   Rect, WorkRect:TRect;
  382.   TopColor, BottomColor: TColor;
  383.   FontHeight: Integer;
  384.   procedure AdjustColors(Bevel: TPanelBevel); {routine supplied by Borland, optimized in TTransBitmap, further optimized in TRichButton}
  385.   begin
  386.     if (Bevel=bvLowered) or (FState=stDown) then {if the bevel is lowered and the button is up}
  387.     begin
  388.       TopColor:=clBtnShadow;          {show the top and bottom colors normally}
  389.       BottomColor:=clBtnHighlight;
  390.     end
  391.     else      {if the bevel is not lowered}
  392.     begin
  393.       TopColor:=clBtnHighlight;  {switch the top and bottom colors}
  394.       BottomColor:=clBtnShadow;
  395.     end;
  396.   end;
  397. begin
  398.   Rect:=GetClientRect;  {get the rectangle that outlines the control}
  399.   WorkRect:=GetWorkRect;  {get the working area}
  400.   if FState=stDown then {if the button is down}
  401.   begin
  402.     OffsetRect(WorkRect, 2, 1);     //move the text down and to the right to similate a click
  403.     InflateRect(WorkRect, -2, -1);  //
  404.   end;
  405.   RichEdit.BoundsRect:=WorkRect;  {make sure the RTF control is positioned correctly}
  406.   RichEdit.Refresh; {make sure that the RTF control is updated (we only need this if the button has been hidden; there should be a way to make this more efficient)}
  407.   RichEdit.Invalidate; {make sure that the RTF control is updated (we only need this if the button has been hidden; there should be a way to make this more efficient)}
  408.   RichEdit.Update; {we need to call both Invalidate and Update; Refresh apparently does *not* do this inside the Paint procedure}
  409.   if FFocus then  {if we should show the focus when the mouse is over the control}
  410.   begin
  411.     if HasFocus then  {if we do actually have the focus}
  412.       Frame3D(Canvas, Rect, FFocusColor, FFocusColor, FFocusWidth)  {show the focus}
  413.     else  {if the mouse isn't over the button}
  414.       Frame3D(Canvas, Rect, clBtnFace, clBtnFace, FFocusWidth); {show the focus outline normally}
  415.   end;
  416.   if BevelOuter<>bvNone then  {if we have an outer bevel}
  417.   begin
  418.     AdjustColors(BevelOuter); {determine the colors to use for the outer bevel}
  419.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth); {draw the outer bevel}
  420.   end;
  421.   Frame3D(Canvas, Rect, Color, Color, BorderWidth); {draw the border}
  422.   if BevelInner<>bvNone then  {if we have an inner bevel}
  423.   begin
  424.     AdjustColors(BevelInner); {determine the colors to use for the outer bevel}
  425.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth); {draw the inner bevel}
  426.   end;
  427. end;
  428.  
  429. procedure TRichButton.SetAlignment(Value: TAlignment);
  430. begin
  431.   FAlignment := Value;
  432.   Invalidate;
  433. end;
  434.  
  435. procedure TRichButton.SetAllowDown(Value:Boolean);  {modified from TTransBitmap}
  436. begin
  437.   if FallowDown<>Value then {if the value is really being changed}
  438.   begin
  439.     FAllowDown:=Value;  {update the variable}
  440.     if (not FAllowDown) and (FState=stDown) then  {if we shouldn't allow the button to be down, but it is}
  441.     begin
  442.       FState:=stUp; {bring the button up}
  443.       Realign;  {realign the controls in the button}
  444.       Invalidate;  {invalidate the button for repainting}
  445.     end;
  446.   end;
  447. end;
  448.  
  449. procedure TRichButton.SetBevelInner(Value: TPanelBevel);
  450. begin
  451.   FBevelInner := Value;
  452.   Realign;
  453.   Invalidate;
  454. end;
  455.  
  456. procedure TRichButton.SetBevelOuter(Value: TPanelBevel);
  457. begin
  458.   FBevelOuter := Value;
  459.   Realign;
  460.   Invalidate;
  461. end;
  462.  
  463. procedure TRichButton.SetBevelWidth(Value: TBevelWidth);
  464. begin
  465.   FBevelWidth := Value;
  466.   Realign;
  467.   Invalidate;
  468. end;
  469.  
  470. procedure TRichButton.SetBorderWidth(Value: TBorderWidth);
  471. begin
  472.   FBorderWidth := Value;
  473.   Realign;
  474.   Invalidate;
  475. end;
  476.  
  477. procedure TRichButton.SetBorderStyle(Value: TBorderStyle);
  478. begin
  479.   if FBorderStyle <> Value then
  480.   begin
  481.     FBorderStyle := Value;
  482.     RecreateWnd;
  483.   end;
  484. end;
  485.  
  486. procedure TRichButton.SetFocus(Value:Boolean);  {modified from TTransBitmap}
  487. begin
  488.   if FFocus<>Value then {if the value is really being changed}
  489.   begin
  490.     FFocus:=Value;  {set the new value}
  491.     Realign;  {realign the controls in the button}
  492.     Invalidate;  {invalidate the button for repainting}
  493.   end;
  494. end;
  495.  
  496. procedure TRichButton.SetFocusColor(Value:TColor);  {modified from TTransBitmap}
  497. begin
  498.   if FFocusColor<>Value then {if the value is really being changed}
  499.   begin
  500.     FFocusColor:=Value; {change the value}
  501.     Invalidate;  {invalidate the button for repainting}
  502.   end;
  503. end;
  504.  
  505. procedure TRichButton.SetFocusWidth(Value:TWidth);  {modified from TTransBitmap}
  506. begin
  507.   if FFocusWidth<>Value then {if the value is really being changed}
  508.   begin
  509.     FFocusWidth:=Value; {change the value}
  510.     Realign;  {realign the controls in the button}
  511.     Invalidate;  {invalidate the button for repainting}
  512.   end;
  513. end;
  514.  
  515. function TRichButton.GetLines:TStrings;
  516. begin
  517.   Result:=RichEdit.Lines;  {get the richedit's lines}
  518. end;
  519.  
  520. procedure TRichButton.SetLines(Value:TStrings);
  521. begin
  522.   RichEdit.Lines:=Value;  {set the richedit's lines}
  523. end;
  524.  
  525. procedure TRichButton.SetState(Value:TRichButtonState); {modified from TTransBitmap}
  526. begin
  527.   if FState<>Value then {if the value is really being changed}
  528.   begin
  529.     if (Value=stDown) and (not FAllowDown) then {if they want the button down, but we don't allow it}
  530.     begin
  531.       if FState=stUp then {if the button is up, disable it, otherwise, bring it up}
  532.         FState:=stDisabled
  533.       else
  534.         FState:=stUp;
  535.     end
  536.     else  {if they want to bring the button up, or they want to put it down and we allow it (or they want to disable it)}
  537.       FState:=Value;  {actually change the state of the button}
  538.     Realign;  {realign the controls in the button}
  539.     Invalidate;  {invalidate the button for repainting}
  540.   end;
  541. end;
  542.  
  543. end.
  544.